﻿using Microsoft.VisualStudio.Diagrams.View;
using Microsoft.VisualStudio.GraphModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace Timtopia.DGMLPosterView
{
    public class ModuleGroup : GroupShape
    {
        DiagramControl diagramControl;
        public static double Radius = 40;
        static ModuleGroup()
        {
            ModuleColor = Colors.Black; // (Color)ColorConverter.ConvertFromString("#d6971f");
            //ModuleColor = (Color)ColorConverter.ConvertFromString("#FF1382CE");
            ModuleBrush = new SolidColorBrush(ModuleColor);
        }

        public ModuleGroup(DiagramControl control)
        {
            this.diagramControl = control;
            //this.DataContext = group.AsNode();
            this.Content = new Grid();
        }

        public static Color ModuleColor;
        public static Brush ModuleBrush;

        protected override void OnRender(System.Windows.Media.DrawingContext drawingContext)
        {
            base.OnRender(drawingContext);
            Pen pen = new Pen(ModuleBrush, 3);
            Rect bounds = new Rect(this.DesiredSize);
            var fill = new SolidColorBrush(new Color { R = 0, G = 0, B = 0, A = 0 });
            //drawingContext.DrawRoundedRectangle(fill, pen, bounds, Radius, Radius);
            Rect canvasBounds = this.Group.GetBounds();
            Vector renderOffset = -new Vector(canvasBounds.X, canvasBounds.Y);

            var node = this.Group.AsNode();

            //foreach (var l in node.IncomingLinks)
            //{
            //    var spatialItem = this.diagramControl.GetSpatialItem(l);
            //    if (spatialItem == null) continue;
            //    var linkVis = this.diagramControl.Canvas.VisualFromItem(spatialItem) as LinkShape;
            //    if (linkVis == null) continue;
            //    var linkGeometry = linkVis.Geometry;

            //    PathGeometry flattenedPathGeometry = linkGeometry.GetFlattenedPathGeometry();
            //    Point endPoint, tangent;
            //    flattenedPathGeometry.GetPointAtFractionLength(1.0, out endPoint, out tangent);
            //    Geometry g = GetArrowGeometry();
            //    TransformGroup tg = new TransformGroup();
            //    TranslateTransform tt;
            //    RotateTransform rt;
            //    Point basePosition = endPoint - 5 * (Vector)tangent;
            //    Point tipPosition = endPoint + 5 * (Vector)tangent;
            //    ComputeTransforms(new Thickness(0), g.Bounds.Size, canvasBounds, tipPosition, basePosition, out rt, out tt);
            //    tg.Children.Add(rt);
            //    tg.Children.Add(tt);
            //    g.Transform = tg;
            //    drawingContext.DrawGeometry(linkVis.Stroke, null, g);
            //}

            //foreach (var v in Group.ChildGroups.AsNodes().Concat(Group.ChildNodes))
            //{
            //    foreach (var l in v.IncomingLinks.Concat(v.OutgoingLinks).Where(l => l.HasCategory(PowerGraphDecomposition.PowerEdgeCategory)))
            //    {
            //        LineGeometry lg = new LineGeometry(GetCenter(l.Source.GetBounds()), GetCenter(l.Target.GetBounds()));
            //        var sg = l.Source.GetGeometry();
            //        Point start = GetIntersectionPoints(lg,sg).First();
            //        var tg = l.Target.GetGeometry();
            //        Point end = GetIntersectionPoints(lg,tg).First();
            //        drawingContext.DrawLine(pen, start + renderOffset, end + renderOffset);
            //    }
            //}
        }
        public static Point[] GetIntersectionPoints(Geometry g1, Geometry g2)
        {
            Geometry og1 = g1.GetWidenedPathGeometry(new Pen(Brushes.Black, 1.0));
            Geometry og2 = g2.GetWidenedPathGeometry(new Pen(Brushes.Black, 1.0));

            CombinedGeometry cg = new CombinedGeometry(GeometryCombineMode.Intersect, og1, og2);

            PathGeometry pg = cg.GetFlattenedPathGeometry();
            Point[] result = new Point[pg.Figures.Count];
            for (int i = 0; i < pg.Figures.Count; i++)
            {
                Rect fig = new PathGeometry(new PathFigure[] { pg.Figures[i] }).Bounds;
                result[i] = new Point(fig.Left + fig.Width / 2.0, fig.Top + fig.Height / 2.0);
            }
            return result;
        }

        private static void ComputeTransforms(Thickness margin, Size shapeSize, Rect realBounds, Point tipPosition, Point basePosition, out RotateTransform rotate, out TranslateTransform translate)
        {
            Vector vector = (Vector)(tipPosition - basePosition);
            double angle = -Vector.AngleBetween(vector, new Vector(1.0, 0.0));
            rotate = new RotateTransform(angle, -margin.Left + shapeSize.Width, -margin.Top + (shapeSize.Height / 2.0));
            translate = new TranslateTransform((tipPosition.X - realBounds.X) - shapeSize.Width, (tipPosition.Y - realBounds.Y) - (shapeSize.Height / 2.0));
        }

        private static Point GetCenter(Rect realBounds, Rect r)
        {
            return new Point((r.Left + r.Right) / 2 - realBounds.X, (r.Top + r.Bottom) / 2 - realBounds.Y);
        }
        private static Point GetCenter(Rect r)
        {
            return new Point((r.Left + r.Right) / 2, (r.Top + r.Bottom) / 2);
        }

        private static Geometry GetArrowGeometry()
        {
            double minHeadWidth = 8;
            double baseCurveDepth = 1;
            double depth = 9;
            PathGeometry geometry2 = new PathGeometry();
            PathFigure figure = new PathFigure
            {
                StartPoint = new Point(depth, minHeadWidth / 2.0)
            };
            LineSegment segment = new LineSegment
            {
                Point = new Point(0.0, minHeadWidth)
            };
            figure.Segments.Add(segment);
            QuadraticBezierSegment segment2 = new QuadraticBezierSegment
            {
                Point1 = new Point(baseCurveDepth, (2.0 * minHeadWidth) / 3.0),
                Point2 = new Point(baseCurveDepth, minHeadWidth / 2.0)
            };
            figure.Segments.Add(segment2);
            QuadraticBezierSegment segment3 = new QuadraticBezierSegment
            {
                Point1 = new Point(baseCurveDepth, minHeadWidth / 3.0),
                Point2 = new Point(0.0, 0.0)
            };
            figure.Segments.Add(segment3);
            figure.IsClosed = true;
            geometry2.Figures.Add(figure);
            return geometry2;
        }
    }
}
